package com.basker.pisces.concurrent.collection;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public abstract class AbstractConcurrentCollectionManager implements IConcurrentCollectionManager {
    private String name;
    private final ConcurrentMap<String, Set<String>> setMap = new ConcurrentHashMap<>(16);
    private Set<String> setNames = Collections.emptySet();

    public AbstractConcurrentCollectionManager(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public Set<String> getSet(String name) {
        Set<String> set = this.setMap.get(name);
        if (set != null) {
            return set;
        } else {
            synchronized (this.setMap) {
                set = this.setMap.get(name);

                if (set == null) {
                    set = createSet(name);
                    if (set != null) {
                        this.setMap.put(name, set);
                        updateSetNames(name);
                    }
                }

                return set;
            }
        }
    }

    @Override
    public Collection<String> getSetNames() {
        return this.setNames;
    }

    public void setName(String name) {
        this.name = name;
    }

    protected abstract Set<String> createSet(String name);

    protected ConcurrentMap<String, Set<String>> getSetMap() {
        return setMap;
    }

    private void updateSetNames(String name) {
        Set<String> setNames = new LinkedHashSet<>(this.setNames.size() + 1);
        setNames.addAll(this.setNames);
        setNames.add(name);
        this.setNames = Collections.unmodifiableSet(setNames);
    }
}
